﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PlanB.ShareDove.ConferenceOrganization.BusinessLayer.DataLayerInterface;
using PlanB.ShareDove.ConferenceOrganization.BusinessLayer.DataLayerInterface.Entities;
using Microsoft.SharePoint;

namespace PlanB.ShareDove.ConferenceOrganization.DataLayer.SharePointDataLayer
{
    /// <summary>
    /// Data layer for the Conference Organization Portal
    /// </summary>
    public partial class SharePointDataLayer : IConferenceOrganizationDataLayerInterface
    {

        /// <summary>
        /// Get list of sessions, filtered by the session day, track and speaker
        /// Leave nulls in those parameters where you don't want any filtering
        /// </summary>
        /// <param name="passedContext">SPWeb from the current context</param>
        /// <param name="day">Day when the session is occuring</param>
        /// <param name="trackId">Id of the track to which the session belong</param>
        /// <returns>IEnumerable List of sessions</returns>
        public IEnumerable<ConferenceSession> GetSessionData(object passedContext, DateTime? day, int? trackId)
        {
            try
            {

                //create context
                PlanB.SharePointCore.Helpers.ContextHelper contextHelper = new PlanB.SharePointCore.Helpers.ContextHelper(passedContext);
                
                
                List<ConferenceSession> returnSessions = new List<ConferenceSession>();

                using (ConferenceOrganizationSolutionDataContext dc = new ConferenceOrganizationSolutionDataContext(contextHelper.Web.Url))
                {

                    //query sessions list
                    var allSessions = from sessions in dc.Sessions select sessions;

                    //
                    //make search refinements if necessary
                    if (day.HasValue) allSessions = allSessions.Where(condition => condition.Slot.Value.Date == day.Value.Date);
                    if (trackId.HasValue) allSessions = allSessions.Where(condition => condition.Track.Id == trackId);
                    foreach (var singleSession in allSessions)
                    {
                        ConferenceSession session = convertSessionItemToConferenceSession(singleSession);
                        returnSessions.Add(session);
                    }
                }

                contextHelper.DisposeContext();

                return returnSessions;
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Error while retreiving sessions from the data layer", ex);
            }

        }

        #region converters and transformers

        /// <summary>
        /// Converts a SessionItem from data context to ConferenceSession object
        /// </summary>
        /// <param name="sessionItem">SessionItem object from datacontext</param>
        /// <returns>ConferenceSession</returns>
        private ConferenceSession convertSessionItemToConferenceSession(SessionsItem sessionItem)
        {
            try
            {
                ConferenceSession session = new ConferenceSession()
                {
                    Id = sessionItem.Id.HasValue ? Convert.ToInt32(sessionItem.Id.Value) : 0,
                    Title = sessionItem.Title,
                    Abstract = sessionItem.Abstract,
                    Duration = sessionItem.Duration.HasValue ? Convert.ToInt32(sessionItem.Duration.Value) : 0,
                    Language = sessionItem.Language,
                    Level = sessionItem.Level,
                    Version = sessionItem.Version.HasValue ? Convert.ToDecimal(sessionItem.Version.Value) : 0,
                    Slot = sessionItem.Slot.HasValue ? (DateTime)(sessionItem.Slot.Value) : DateTime.Now,
                };

                if (sessionItem.Track != null)
                {
                    session.Track = new ConferenceTrack()
                    {
                        Id = sessionItem.Track.Id.HasValue ? Convert.ToInt32(sessionItem.Track.Id.Value) : 0,
                        Description = sessionItem.Track.Description,
                        Name = sessionItem.Track.Title,
                        Products = sessionItem.Track.Products,
                        Version = sessionItem.Track.Version.HasValue ? Convert.ToDecimal(sessionItem.Track.Version.Value) : 0
                    };
                }

                if (sessionItem.Room != null)
                {
                    session.Room = new ConferenceRoom()
                    {
                        Id = sessionItem.Room.Id.HasValue ? Convert.ToInt32(sessionItem.Room.Id.Value) : 0,
                        Name = sessionItem.Room.Title,
                        Address = sessionItem.Room.Address,
                        ParticipantsNumber = sessionItem.Room.ParticipantsNumber.HasValue ? Convert.ToInt32(sessionItem.Room.ParticipantsNumber.Value) : 0,
                        SchemaImageUrl = sessionItem.Room.SchemaImageUrl,
                        Version = sessionItem.Room.Version.HasValue ? Convert.ToDecimal(sessionItem.Room.Version.Value) : 0
                    };
                }

                if (sessionItem.Speakers != null)
                {
                    List<ConferenceParticipant> tmpSpeakers = new List<ConferenceParticipant>();

                    foreach (AttendeesItem speaker in sessionItem.Speakers)
                    {
                        tmpSpeakers.Add(convertAttendeeItemToConferenceParticipant(speaker));
                    }

                    session.Speakers = tmpSpeakers;
                }

                return session;
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Error in converting SeesionItem to ConferenceSession", ex);
            }
        }

        /// <summary>
        /// Converts the atendee item to ConferenceParticipant
        /// </summary>
        /// <param name="atendee">atendee</param>
        /// <returns>participant</returns>
        private ConferenceParticipant convertAttendeeItemToConferenceParticipant(AttendeesItem atendee)
        {
            try
            {
                ConferenceParticipant part = new ConferenceParticipant();

                part.Id = atendee.Id.HasValue ? Convert.ToInt32(atendee.Id.Value) : 0;

                part.Address = new ConferenceAddress();
                part.Address.AddressLine1 = atendee.AddressLine1;
                part.Address.AddressLine2 = atendee.AddressLine2;
                part.Address.City = atendee.City;
                part.Address.Zip = atendee.ZIP;
                part.Address.Province = atendee.Province;
                part.Address.Phone = atendee.Phone;
                part.Address.Fax = atendee.Fax;
                part.Address.EMail = atendee.Email;
                part.Address.Latitude = atendee.Latitude;
                part.Address.Longitude = atendee.Longitude;
                if (atendee.Country != null)
                {
                    part.Address.Country = new ConferenceCountry();
                    part.Address.Country.Id = atendee.Country.Id.HasValue ? Convert.ToInt32(atendee.Country.Id.Value) : 0;
                    part.Address.Country.Iso3166_1 = atendee.Country.Iso3166_1;
                    part.Address.Country.Name = atendee.Country.Title;
                }

                part.BankAccountInformation = new ConferenceBankAccount();
                part.BankAccountInformation.BankAccount = atendee.BankAccount;
                part.BankAccountInformation.BankCode = atendee.BankCode;
                part.BankAccountInformation.BankIbanCode = atendee.BankIbanCode;
                part.BankAccountInformation.BankName = atendee.BankName;
                part.BankAccountInformation.BankSwiftCode = atendee.BankSwiftCode;
                if (atendee.BankCountry != null)
                {
                    part.BankAccountInformation.BankCountry = new ConferenceCountry();
                    part.BankAccountInformation.BankCountry.Id = atendee.BankCountry.Id.HasValue ? Convert.ToInt32(atendee.BankCountry.Id.Value) : 0;
                    part.BankAccountInformation.BankCountry.Iso3166_1 = atendee.BankCountry.Iso3166_1;
                    part.BankAccountInformation.BankCountry.Name = atendee.BankCountry.Title;
                }

                if (atendee.Company != null)
                {
                    part.Company = convertCompantItemToConferenceCompany(atendee.Company);
                }

                part.LiveId = atendee.LiveId;
                part.Name = atendee.Title;
                part.PersonTitle = atendee.PersonTitle;
                part.PhotoUrl = atendee.PhotoUrl;
                part.PositionInCompany = atendee.PositionInCompany;
                part.PreferredLanguage = atendee.PreferredLanguage;

                if (atendee.Sex.HasValue)
                {
                    part.Sex = atendee.Sex.Value.ToString() == "M" ? ConferenceOrganizationSolutionEnums.PersonSex.Male : ConferenceOrganizationSolutionEnums.PersonSex.Female;
                }

                part.HotelCostsCovered = atendee.HotelCostsCovered.HasValue ? atendee.HotelCostsCovered.Value : false;
                part.IsBeingPaidForParticipation = atendee.IsBeingPaidForParticipation.HasValue ? atendee.IsBeingPaidForParticipation.Value : false;
                part.IsJournalist = atendee.IsJournalist.HasValue ? atendee.IsJournalist.Value : false;
                part.IsPartner = atendee.IsPartner.HasValue ? atendee.IsPartner.Value : false;
                part.IsPaying = atendee.IsPaying.HasValue ? atendee.IsPaying.Value : false;
                part.IsSpeaker = atendee.IsSpeaker.HasValue ? atendee.IsSpeaker.Value : false;
                part.IsSponsor = atendee.IsSponsor.HasValue ? atendee.IsSponsor.Value : false;
                part.IsVisitor = atendee.IsVisitor.HasValue ? atendee.IsVisitor.Value : false;
                part.TravelingCostsCovered = atendee.TravelingCostsCovered.HasValue ? atendee.TravelingCostsCovered.Value : false;

                if (atendee.Profession != null)
                {
                    part.Profession = new ConferencePersonProfession();
                    part.Profession.Id = atendee.Profession.Id.HasValue ? Convert.ToInt32(atendee.Profession.Id.Value) : 0;
                    part.Profession.Name = atendee.Profession.Title;
                    part.Profession.Version = atendee.Profession.Version.HasValue ? Convert.ToDecimal(atendee.Profession.Version.Value) : 0;
                }

                part.Version = atendee.Version.HasValue ? Convert.ToDecimal(atendee.Version.Value) : 0;

                return part;
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Error in converting AttendeeItem to ConferenceParticipant", ex);
            }
        }

        /// <summary>
        /// Converts a company item to the ConferenceCompany
        /// </summary>
        /// <param name="companiesItem">companiesItem</param>
        /// <returns>ConferenceCompany</returns>
        private ConferenceCompany convertCompantItemToConferenceCompany(CompaniesItem companiesItem)
        {
            try
            {
                ConferenceCompany company = new ConferenceCompany();

                company.Id = companiesItem.Id.HasValue ? Convert.ToInt32(companiesItem.Id.Value) : 0;

                company.Address = new ConferenceAddress();
                company.Address.AddressLine1 = companiesItem.AddressLine1;
                company.Address.AddressLine2 = companiesItem.AddressLine2;
                company.Address.City = companiesItem.City;
                company.Address.Zip = companiesItem.ZIP;
                company.Address.Province = companiesItem.Province;
                company.Address.Phone = companiesItem.Phone;
                company.Address.Fax = companiesItem.Fax;
                company.Address.EMail = companiesItem.Email;
                company.Address.Latitude = companiesItem.Latitude;
                company.Address.Longitude = companiesItem.Longitude;
                if (company.Address.Country != null)
                {
                    company.Address.Country = new ConferenceCountry();
                    company.Address.Country.Id = companiesItem.Country.Id.HasValue ? Convert.ToInt32(companiesItem.Country.Id.Value) : 0;
                    company.Address.Country.Iso3166_1 = companiesItem.Country.Iso3166_1;
                    company.Address.Country.Name = companiesItem.Country.Title;
                }

                company.BankAccountInformation = new ConferenceBankAccount();
                company.BankAccountInformation.BankAccount = companiesItem.BankAccount;
                company.BankAccountInformation.BankCode = companiesItem.BankCode;
                company.BankAccountInformation.BankIbanCode = companiesItem.BankIbanCode;
                company.BankAccountInformation.BankName = companiesItem.BankName;
                company.BankAccountInformation.BankSwiftCode = companiesItem.BankSwiftCode;
                if (company.BankAccountInformation.BankCountry != null)
                {
                    company.BankAccountInformation.BankCountry = new ConferenceCountry();
                    company.BankAccountInformation.BankCountry.Id = companiesItem.BankCountry.Id.HasValue ? Convert.ToInt32(companiesItem.BankCountry.Id.Value) : 0;
                    company.BankAccountInformation.BankCountry.Iso3166_1 = companiesItem.BankCountry.Iso3166_1;
                    company.BankAccountInformation.BankCountry.Name = companiesItem.BankCountry.Title;
                }

                company.IsMedia = companiesItem.IsMedia.HasValue ? companiesItem.IsMedia.Value : false;

                company.ManagerName = companiesItem.ManagerName;
                company.Name = companiesItem.Title;
                company.PartnerStatus = companiesItem.PartnerStatus;
                company.PointOfContact = companiesItem.PointOfContact;

                //TODO: Change Sponsoring Status to multiple lookup
                if (companiesItem.SponsoringStatus != null)
                {
                    List<ConferenceCompanySponsoringStatus> tmpStatuses = new List<ConferenceCompanySponsoringStatus>();

                    ConferenceCompanySponsoringStatus thisStatus = new ConferenceCompanySponsoringStatus();
                    thisStatus.Id = companiesItem.SponsoringStatus.Id.HasValue ? Convert.ToInt32(companiesItem.SponsoringStatus.Id.Value) : 0;
                    thisStatus.Name = companiesItem.SponsoringStatus.Title;
                    thisStatus.DiscountForEmployees = companiesItem.SponsoringStatus.DiscountForEmployees.HasValue ? Convert.ToInt32(companiesItem.SponsoringStatus.DiscountForEmployees.Value) : 0;
                    thisStatus.Version = companiesItem.SponsoringStatus.Version.HasValue ? Convert.ToDecimal(companiesItem.SponsoringStatus.Version.Value) : 0;
                    tmpStatuses.Add(thisStatus);
                    company.SponsoringStatus = tmpStatuses;
                }


                company.Version = companiesItem.Version.HasValue ? Convert.ToDecimal(companiesItem.Version.Value) : 0;

                return company;
            }
            catch (Exception ex)
            {
                throw new ApplicationException("Error in converting CompaniesItem to ConferenceCompany", ex);
            }
        }
        #endregion
    }
}
